Context (otel)
https://opentelemetry.io/docs/specs/otel/context/
/mrsekut-book-4814401035/097: 5章 コンテキスト、バゲッジ、プロパゲーター
あんまりちゃんと呼んでないmrsekut.icon
GPT-4o.icon
これは OpenTelemetry の Context API の仕様説明ですね。
要するに 「リクエストや処理の実行単位ごとに状態(トレースIDやユーザー情報など)を安全に持ち回る仕組み」 を定義したものです。
ざっくりまとめ
Context は「実行スコープに結びついた値の入れ物」で、非同期処理やAPI境界をまたいでも状態を引き継ぐために使う。
Immutable(不変):値を書き込むたびに新しい Context が作られる。
Key は他のライブラリと衝突しないようにユニークに作られる。
Get / Set で値を取得・設定する。
言語によっては「現在の Context」を暗黙的に扱える(グローバル操作:Attach / Detach)。
主な用途はトレースやBaggage (otel)(リクエストに紐づくメタ情報)などのクロスカッティング関心事。
図解イメージ
code:_
処理フロー
┌────────────┐
│Context │ key: trace_id -> "abc123"
│(immutable) │ key: user_id -> "42"
└────────────┘
│
setValue(key, val) => 新しい Context が返る
▼
┌────────────┐
│新しいContext│ key: trace_id -> "abc123"
│ │ key: user_id -> "84"
└────────────┘
Contextの中に、Baggage (otel)やSpanなどが入っている
code:_
Context(コンテナ)
├─ Span(今の処理のトレース情報)
├─ Baggage(key-valueの追加データ)
└─ 他にもカスタムデータやSDKが使う状態が入る
TSでのサンプルコード(OpenTelemetry API風)
OpenTelemetry の context API を TypeScript で使うとこんな感じです。
code:ts
import { context, createContextKey } from '@opentelemetry/api';
// 1. Key を作る
const USER_ID_KEY = createContextKey('user-id');
// 2. 初期 Context(空)
let ctx = context.active();
// 3. 値をセット(新しい Context が返る)
ctx = ctx.setValue(USER_ID_KEY, '42');
// 4. 値を取得
const userId = ctx.getValue(USER_ID_KEY);
console.log(userId); // "42"
// 5. 現在の Context に紐づけて非同期処理でも保持
import { context as otContext } from '@opentelemetry/api';
function doSomething() {
const currentUserId = otContext.active().getValue(USER_ID_KEY);
console.log(Current user in async task: ${currentUserId});
}
otContext.with(ctx, () => {
// この中の処理は ctx が current context になる
doSomething(); // => "Current user in async task: 42"
});
仕様のポイント
1. CreateKey(name)
デバッグ用の名前はあくまで説明用で、ユニーク性はKey自体が持つ。
他ライブラリとキー衝突しないための仕組み。
2. GetValue(context, key)
指定したキーの値を取り出す。
見つからなければ undefined。
3. SetValue(context, key, value)
元の Context は変更せず、新しい Context を返す(不変性)。
4. グローバル操作 (Optional)
GetCurrentContext … 現在の実行単位に紐づく Context を取得。
AttachContext … 指定 Context を「現在の実行単位」に関連付ける。
DetachContext … Attach 前の Context に戻す。
5. 非同期でも状態を維持
Promiseやイベントループを跨いでも、context.with や Attach/Detach で値を保持できる。
よくある利用例
トレーシング:リクエスト開始時に Trace ID を Context に入れておく。
Baggage:ユーザーIDやテナントIDなどをリクエスト全体で共有。
Correlation ID:ログやメトリクスで同じリクエストを紐づける。
もし希望あれば、この仕様を元に 「OpenTelemetryを使わずにContext仕組みを自作するTSコード」 も書けます。
そうすると内部のAttach/DetachやImmutable設計がよくわかる形になります。